/**
@author		Jong Min, Lee
@date		  10/01/2014
@breif		dicom series class

copyright(c) Tae Young Soft. All right reserved. 2014
*/
#pragma once

#include <vector>

#include "Taurus_Util/Macros.h"
#include "Taurus_DcmData/Defines.h"

//forward declarations
class ISeriesInfo;
class CDcmStudy;
class CDcmInstance;

/**
@brief		dicom series class
*/
class TAURUS_DCMDATA_EXPORT CDcmSeries
{
private:
  /**
  @brief		default constructor
  */
  CDcmSeries();

  DISALLOW_COPY_AND_ASSIGN(CDcmSeries);

public:
  friend class CDcmSeriesProducer;

  /**
  @brief		destructor
  */
  ~CDcmSeries();

  /**
  @brief		increase reference count by 1
  */
  inline void increaseRefCount()
  {
    m_theRefCount++;
  }

  /**
  @brief		decrease reference count by 1
  */
  inline void decreaseRefCount()
  {
    m_theRefCount--;
  }

  /**
  @brief		get reference count
  */
  inline int getRefCount() const
  {
    return m_theRefCount;
  }

  /**
  @brief		get pointer to parent study
  @return		pointer to parent dicom study if this has it, nullptr if not
  */
  inline CDcmStudy* getParent() const
  {
    return m_theParent;
  }

  /**
  @brief		set parent dcm study
  @param		parent pointer to dcm study be parent
  */
  inline void setParent(CDcmStudy* parent)
  {
    m_theParent = parent;
  }

  /**
  @brief		get series key
  @return		series key
  */
  inline const TCHAR* getKey() const
  {
    return m_theKey;
  }

  /**
  @brief		get modality
  */
  inline const TCHAR* getModality() const
  {
    return m_theModality;
  }

  /**
  @brief		check whether dcm series is none image series or not
  @return		return TRUE if dcm series is noe image series, FALSE if not
  */
  BOOL isNoneImage() const;

  /**
  @brief		get the number of dcm instance belong to this
  @return		the number of dcm instance belong to this
  */
  inline unsigned int getNumInstances() const
  {
    return m_theInstances.size();
  }

  /**
  @brief		access to a dcm instance
  @param		index the index number of dcm instance to be accessed
  @return		pointer to dcm instance if found, nullptr if not
  */
  CDcmInstance* getInstance(const unsigned int index);
  const CDcmInstance* getInstance(const unsigned int index) const;

  /**
  @brief		add a dcm instance to dcm series
  @param		instance pointer to dcm instance to be added
  @return		ERROR_SUCCESS if succeeds, an error code otherwise
  */
  DWORD addInstance(CDcmInstance* instance);

  /**
  @brief		find a dcm instance by instance key
  @param		key null-terminated string represents series key
  @return		pointer to dcm instance if found, nullptr if not
  */
  CDcmInstance* findInstance(const TCHAR* key) const;

  /**
  @brief		remove not referenced instances
  */
  DWORD removeNotRefInstances();

private:
  /**
  @brief		initialize dcm series
  */
  void init();

  /**
  @brief		destroy dcm series. this method should be only used in destruction
  */
  void destroy();

  /**
  @brief		remove all dcm instances belong to dcm series
  */
  void removeAllInstances();

private:

  //reference count
  int m_theRefCount;

  //parent dcm study
  CDcmStudy* m_theParent;

  //series key
  CString m_theKey;

  //modality
  CString m_theModality;

  //instances
  std::vector<CDcmInstance*> m_theInstances;
};

/**
@brief		dcm series producer class
*/
class TAURUS_DCMDATA_EXPORT CDcmSeriesProducer
{
public:
  /**
  @brief		create a new dcm series by using series information
  @param		seriesInfo series information
  @param    parent pointer to dcm study to be parent
  @param    outSeries variable in which pointer to new dcm series is stored
  @return		ERROR_SUCCESS upon success, an error code otherwise
  */
  static DWORD produce(ISeriesInfo& seriesInfo,
                       CDcmStudy* parent,
                       CDcmSeries*& outSeries);
};
